package com.cxlin.base.view.recyclerview

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.databinding.library.baseAdapters.BR
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView

/**
 *
 * @Author: chenxunlin
 * @Date: 2024/4/26 10:04
 */
open class BaseAdapter<T : BaseItem>(private val layoutId: Int, val handler: Handler<T>? = null) :
    ListAdapter<T, BaseAdapter.ViewHolder<T>>(DiffCallback()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<T> {
        return ViewHolder(
            DataBindingUtil.inflate(
                LayoutInflater.from(parent.context),
                layoutId,
                parent,
                false
            ), handler
        )
    }

    override fun onBindViewHolder(holder: ViewHolder<T>, position: Int) {
        holder.bind(getItem(position))
    }

    /**
     * 重写 提交数据方法, 让它必定以新数据集合对象传入;
     * 这种方式 只是写法简单. 有时会导致不必要的集合重装.
     */
    override fun submitList(list: MutableList<out T>?) {
        val newData = mutableListOf<T>()
        if (list != null) {
            newData.addAll(list)
        }
        super.submitList(newData)
    }

    class ViewHolder<T : BaseItem>(val binding: ViewDataBinding, private val handler: Handler<T>?) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(item: BaseItem?) {
            //重置 状态标记
            item?.hasChanged = false
            binding.setVariable(BR.item, item)
            binding.setVariable(BR.handler, handler)
            // 立即绑定
            binding.executePendingBindings()
        }
    }

    class DiffCallback<T : BaseItem> : DiffUtil.ItemCallback<T>() {
        /**
         * 比较两个条目对象  是否为同一个Item
         * 如果是 Paging + Room, 则需要用 oldItem.getItemId() == newItem.getItemId() 方式
         */
        override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
            return oldItem === newItem
        }

        /**
         * 再确定为同一条目的情况下;  再去比较 item 的内容是否发生变化;
         * 我们使用 状态标识方式; 如果使用 Paging, 则应用 Equals 方式;
         * @return true: 代表无变化;  false: 有变化;
         */
        override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
            return !oldItem.hasChanged
        }
    }

    /**
     * item 事件响应基类, 需提供具体的实体类泛型;
     */
    abstract class Handler<T : BaseItem> {
        abstract fun onClick(view: View, info: T)
    }
}